'use strict';

var express = require('express');
var path = require('path');
var _ = require('underscore');
var config = require('./config');
var fileUpload = require('express-fileupload');
var fs = require('fs');
var mkdirp = require("mkdirp");
var moment = require('moment');
var uuid = require('node-uuid');
var crypto = require('crypto');
var argv = require('yargs').argv;
var job = require('./jobs');
var AdmZip = require('adm-zip');

var app = express();
var httpPort = Number(argv._[0]) || 3000;
app.set('views', './views');
app.set('view engine', 'jade');
app.use('/static', express.static('static'));
app.use(fileUpload());

app.post('/upload', function (req, res, next) {
  var tag = req.query.tag;
  var memo = req.query.memo;
  var relativePath = req.query.relativePath;
  var project = _.find(config.projects, function (p) { return p.name == req.query.project; });
  if (project == undefined) {
    res.json({ "success": false, "stop": true, "message": 'project:' + req.query.project + ' 不存在' });
    return;
  }
  ProjectInit(project);
  if (project.directory.substr(project.directory.length - 1) == "\\") {
    project.directory = project.directory.substr(0, project.directory.length - 1);
  }

  var user = _.find(project.users, function (p) { return p.account == req.query.account; });
  if (user == undefined) {
    res.json({ "success": false, "stop": true, "message": '帐号密码错误' });
    return;
  }

  var sampleFile;
  if (!req.files) {
    res.json({ "success": false, "stop": false, "message": '没有上传文件' });
    return;
  }
  sampleFile = req.files.file;
  var password = crypto.createHash('md5').update(new Buffer(sampleFile.data)).digest('hex') + user.password + relativePath;
  var password = crypto.createHash('md5').update(password).digest('hex');
  if (password != req.query.password) {
    res.json({ "success": false, "stop": true, "message": '帐号密码错误' });
    return;
  }

  var currentPath = path.resolve();

  //慢慢有点复杂了，应该重构代码
  if(relativePath.indexOf('[[zipzip]]') == 0 ){
    //zip打包上传业务逻辑处理
    var zipFileName = relativePath.replace('[[zipzip]]','');
    var zipFileFullPath = path.normalize(currentPath + "\\zip\\" + zipFileName);
    CreateDire(currentPath + "\\zip\\");
    sampleFile.mv(zipFileFullPath, function (err) {
      if (err) {
        res.json({ "success": false, "stop": false, "message": 'zip包上传错误' + err });
        return;
      } else {
        console.log(zipFileFullPath + "上传成功");
        res.json({ "success": true, "stop": false, "message": '上传成功，服务器正在解压处理，如果文件大需要消耗较多时间' });

        var zip = new AdmZip(zipFileFullPath);
        var zipEntries = zip.getEntries(); 
        var fileUuid = uuid.v1().substr(0, 8);
        var yyyymmdd = moment().format('YYYYMMDD');
        var dire = path.resolve('zip', zipFileName.split('.')[0]) +"\\";

        zipEntries.forEach(function(zipEntry) {
          console.log(zipEntry.entryName);
          var fileInfo = FileFormat(dire + zipEntry.entryName);
          if(fileInfo.fullName == "underscore-min.js"){
            console.log(123);
          }
          zip.extractEntryTo(zipEntry.entryName,fileInfo.directory,false,true);
          
          relativePath = "\\" + zipEntry.entryName;
          var logInfo = CreateLogInfo(relativePath,currentPath,project.name,project.directory,tag,memo,user.account,fileUuid,yyyymmdd);
          logInfo.log.new = "\\zip\\"+zipFileName.split('.')[0]+"\\" + zipEntry.entryName;

          FileHandler(logInfo.log.target, currentPath + logInfo.log.new, project.fileHandlers, currentPath);
          FileAppend(logInfo.logPath, JSON.stringify(logInfo.log) + ',');
          CreateDire(FileFormat(project.directory + logInfo.log.target).directory);
          fs.createReadStream(currentPath + logInfo.log.new).pipe(fs.createWriteStream(project.directory + logInfo.log.target));
        });
        console.log('end');
      }
    });
  }
  else{
    //单个文件上传
    var filePath = project.directory + relativePath;
    var directory = filePath.substr(0, filePath.lastIndexOf("\\"));

    CreateDire(directory, function (err) {
      if (err) {
        console.error(err);
        res.json({ "success": false, "stop": false, "message": '创建目录出错' + directory });
        return;
      }
    });
    
    var logInfo = CreateLogInfo(relativePath,currentPath,project.name,project.directory,tag,memo,user.account
              ,uuid.v1().substr(0, 8), moment().format('YYYYMMDD'));
    
    console.log(logInfo.log);

    sampleFile.mv(currentPath + logInfo.log.new, function (err) {
      if (err) {
        res.json({ "success": false, "stop": false, "message": '错误' + err });
        return;
      } else {
        console.log(filePath + "上传成功");
        //根据配置对文件做进一步的处理
        FileHandler(logInfo.log.target,currentPath + logInfo.log.new, project.fileHandlers,currentPath);
        //写入log
        FileAppend(logInfo.logPath, JSON.stringify(logInfo.log) + ',');
        //将新文件copy到 project.directory + log.target
        fs.createReadStream(currentPath + logInfo.log.new).pipe(fs.createWriteStream(project.directory + logInfo.log.target));
        res.json({ "success": true, "stop": false, "message": '上传成功' });
        return;
      }
    });
  }
});

app.listen(httpPort);
console.log('The depolyServer is now ready to accept connections on port %s',httpPort);
job.run();



//初始化Project目录
function ProjectInit(project) {
  var basePath = path.normalize(path.resolve('data', project.name));
  var historyPath = path.normalize(path.resolve('data', project.name, 'history'));
  CreateDire(basePath);
  CreateDire(historyPath);
}


//创建目录 同步
function CreateDire(path, cb) {
  mkdirp.sync(path, function (err) {
    if (cb) cb(err);
    if (err) {
      console.error('创建目录出错' + err);
      return;
    }
  });
}


//创建日志记录对象
function CreateLogInfo(relativePath,currentPath,projectName,projectDirectory,tag,memo,account,fileUuid,yyyymmdd){
    var fileInfo = FileFormat(relativePath);
    fileUuid = fileUuid || uuid.v1().substr(0, 8);
    var fileOld = fileInfo.directory + tag + '-' + fileInfo.name + '-old-' + fileUuid;
    var fileNew = fileInfo.directory + tag + '-' + fileInfo.name + '-new-' + fileUuid;
    if (fileInfo.hasExtension) {
      fileOld = fileOld + '.' + fileInfo.extension;
      fileNew = fileNew + '.' + fileInfo.extension;
    }
    yyyymmdd = yyyymmdd || moment().format('YYYYMMDD');
    var historyPath = path.resolve('data', projectName, 'history', yyyymmdd);

    var logPath = path.normalize(path.resolve('data', projectName) + '\\' + yyyymmdd + '-'+tag+'.json');
    var log = {
      data: moment().format('YYYY-MM-DD HH:mm:ss'),
      tag: tag,
      account: account,
      memo: memo,
      target: relativePath,
      old: path.normalize(historyPath + fileOld).replace(currentPath, ''),
      new: path.normalize(historyPath + fileNew).replace(currentPath, '')
    };
    CreateDire(historyPath + fileInfo.directory);
    if (fs.existsSync(projectDirectory + relativePath)) {
      fs.createReadStream(projectDirectory + relativePath).pipe(fs.createWriteStream(currentPath + log.old));
    } else {
      log.old = '';
    }

    return {
      log:log,
      logPath:logPath
    };
}


//向某个文件追加内容
function FileAppend(file, content) {
  fs.writeFileSync(file, content, { 'flag': 'a' }, function (err) {
    if (err) {
      throw err;
    }
  });
}

function FileFormat(filePath) {
  filePath = path.normalize(filePath);
  var directory = ''; 
  var name = '';
  var extension = '';
  var hasExtension = true;
  var fullName = '';

  var index = filePath.lastIndexOf('\\');
  if (index != -1) {
    directory = filePath.substr(0, index + 1);
    filePath = filePath.substr(index + 1);
  }
  var index = filePath.lastIndexOf('.');
  if (index != -1) {
    fullName = filePath;
    name = filePath.substr(0, index);
    extension = filePath.substr(index + 1);
  } else {
    fullName = filePath;
    name = filePath;
    hasExtension = false;
  }
  return {
    directory: directory,
    fullName: fullName,
    name: name,
    extension: extension,
    hasExtension: hasExtension
  };
}

function FileHandler(target, filePath, fileHandlers,currentPath) {
  fileHandlers = fileHandlers || [];
  if (fileHandlers.constructor == Object) fileHandlers = [fileHandlers];
  if (fileHandlers.constructor != Array) return;
  for (var i = 0, item; item = fileHandlers[i]; i++) {
    if(item.filePath.toLocaleLowerCase() == target.toLocaleLowerCase()){
      for(var j=0,rule;rule=item.rules[j];j++){
        switch(rule.name.toLocaleLowerCase()){
          case "a":
            fs.createReadStream(currentPath + rule.p1).pipe(fs.createWriteStream(filePath));
            break;
          case "b":
            var content = fs.readFileSync(filePath,"utf-8");
            content = content.replace(rule.p1,rule.p2);
            fs.writeFileSync(filePath,content,{'flag':'w'});
            break;
          case "c":
            FileAppend(filePath,'\n'+rule.p1);
            break;
        }
      }
    }
  }
}